home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / libs / unixlib.lha / unix / src / dir.c < prev    next >
C/C++ Source or Header  |  1996-11-10  |  3KB  |  174 lines

  1. #include "amiga.h"
  2. #include "dir_data.h"
  3. #include <string.h>
  4.  
  5. /* opendir/readdir/etc ... emulation w/ stat support hack */
  6.  
  7. static void free_entries(iDIR * info)
  8. {
  9.     struct idirect *scan = info->files;
  10.  
  11.     while (scan) {
  12.     struct idirect *next = scan->next;
  13.  
  14.     free(scan);
  15.     scan = next;
  16.     }
  17. }
  18.  
  19. static int gobble_dir(DIR * dir)
  20. {
  21.     iDIR *info = (iDIR *) dir->dd_buf;
  22.     long ioerr;
  23.     struct idirect **last = &info->files;
  24.  
  25.     free_entries(info);
  26.     last_info = 0;
  27.     info->files = 0;
  28.     dir->dd_loc = 0;
  29.     while (ExNext(dir->dd_fd, &info->fib)) {
  30.     u_short namlen = strlen(info->fib.fib_FileName);
  31.     u_short reclen = namlen + 1 + offsetof(struct idirect, entry.d_name);
  32.     struct idirect *newentry = malloc(reclen);
  33.     struct direct *entry;
  34.  
  35.     if (!newentry) {
  36.         errno = ENOMEM;
  37.         return 0;
  38.     }
  39.     newentry->next = 0;
  40.     *last = newentry;
  41.     last = &newentry->next;
  42.  
  43.     newentry->handler = (long)((struct FileLock *)((long)dir->dd_fd << 2))->fl_Task;
  44.     newentry->numblocks = info->fib.fib_NumBlocks;
  45.     newentry->size = info->fib.fib_Size;
  46.     newentry->date = info->fib.fib_Date;
  47.     newentry->type = info->fib.fib_DirEntryType;
  48.     newentry->protection = info->fib.fib_Protection;
  49.  
  50.     entry = &newentry->entry;
  51.     entry->d_ino = info->fib.fib_DiskKey;
  52.     entry->d_reclen = reclen;
  53.     entry->d_namlen = namlen;
  54.     entry->d_off = dir->dd_loc++;
  55.     strcpy(entry->d_name, info->fib.fib_FileName);
  56.     }
  57.     info->pos = info->files;
  58.     dir->dd_loc = 0;
  59.     ioerr = IoErr();
  60.     if (ioerr == ERROR_NO_MORE_ENTRIES)
  61.     return 1;
  62.  
  63.     errno = convert_oserr(ioerr);
  64.     return 0;
  65. }
  66.  
  67. DIR *opendir(const char *dirname)
  68. {
  69.     DIR *new = malloc(sizeof *new);
  70.     iDIR *info = malloc(sizeof *info);
  71.     char *dircopy = malloc(strlen(dirname) + 1);
  72.  
  73.     __chkabort();
  74.     if (new && dircopy && info) {
  75.     new->dd_buf = (char *) info;
  76.     new->dd_size = sizeof *info;
  77.  
  78.     info->files = info->pos = 0;
  79.     info->seeked = 0;
  80.     info->dirname = dircopy;
  81.     strcpy(dircopy, dirname);
  82.     info->cdir = _get_cd();
  83.  
  84.     if ((new->dd_fd = Lock(dirname, ACCESS_READ)) &&
  85.         Examine(new->dd_fd, &info->fib)) {
  86.         if (gobble_dir(new))
  87.         return new;
  88.     } else
  89.         errno = convert_oserr(IoErr());
  90.     closedir(new);
  91.     return 0;
  92.     }
  93.     errno = ENOMEM;
  94.     if (new)
  95.     free(new);
  96.     if (dircopy)
  97.     free(dircopy);
  98.     if (info)
  99.     free(info);
  100.  
  101.     return 0;
  102. }
  103.  
  104. void closedir(DIR * dir)
  105. {
  106.     iDIR *info = (iDIR *) dir->dd_buf;
  107.  
  108.     __chkabort();
  109.     last_info = 0;
  110.     free_entries(info);
  111.     free(info->dirname);
  112.     if (dir->dd_fd)
  113.     UnLock(dir->dd_fd);
  114.     free(dir->dd_buf);
  115.     free(dir);
  116. }
  117.  
  118. struct direct *readdir(DIR * dir)
  119. {
  120.     iDIR *info = (iDIR *) dir->dd_buf;
  121.     struct direct *entry = 0;
  122.  
  123.     __chkabort();
  124.     if (info->seeked) {
  125.     long cloc = 0;
  126.     struct idirect *pos;
  127.  
  128.     pos = info->files;
  129.  
  130.     while (cloc < dir->dd_loc && pos) {
  131.         cloc++;
  132.         pos = pos->next;
  133.     }
  134.     /*if (cloc != dir->dd_loc) error ...
  135.        This doesn't seem to be defined very precisely */
  136.     info->pos = pos;
  137.     info->seeked = 0;
  138.     }
  139.     if (info->pos) {
  140.     entry = &info->pos->entry;
  141.  
  142.     last_info = info;
  143.     last_entry = info->pos;
  144.  
  145.     info->pos = info->pos->next;
  146.     dir->dd_loc++;
  147.     }
  148.     return entry;
  149. }
  150.  
  151. long telldir(DIR * dir)
  152. {
  153.     __chkabort();
  154.     return dir->dd_loc;
  155. }
  156.  
  157. void seekdir(DIR * dir, long loc)
  158. {
  159.     iDIR *info = (iDIR *) dir->dd_buf;
  160.  
  161.     __chkabort();
  162.     info->seeked = 1;
  163.     dir->dd_loc = loc;
  164. }
  165.  
  166. #if 0
  167. void rewwinddir(DIR * dir)
  168. {
  169.     __chkabort();
  170.     gobble_dir(dir);
  171. }
  172.  
  173. #endif
  174.